"use client";

import { MacroAction } from "@/src/types/types.v1";
import { Box, Button } from "@chakra-ui/react";
import { useEffect, useRef, useState } from "react";
import _ from "lodash";
import { DndContext, MouseSensor, useSensor, useSensors } from "@dnd-kit/core";
import { SortableContext } from "@dnd-kit/sortable";
import MacroActionItem from "./MacroActionItem";
import { v4 as uuidv4 } from "uuid";
import { useTranslation } from "@/src/i18n";

function MacroActionEditor({
  actions,
  delay,
  useDelay,
  onChange,
  onRecord,
}: {
  actions: MacroAction[];
  delay: number;
  useDelay: boolean;
  onChange: (actions: MacroAction[]) => void;
  onRecord: (start: boolean) => void;
}) {
  const { t } = useTranslation("");
  const [startRecord, setStartRecord] = useState(false);

  const startRec = (start: boolean, time: number) => {
    if (start) {
      startTime.current = time;
    }
    setStartRecord(start);
    onRecord(start);
  };

  const startTime = useRef(0);
  const actionsRef = useRef<MacroAction[]>([]);
  actionsRef.current = actions;

  useEffect(() => {
    const addAction = (event: any) => {
      event.preventDefault();
      if (event instanceof KeyboardEvent) {
        let keyCode = event.code;
        if (event.repeat) {
          return;
        } else if (keyCode === "" && event.key === "Shift") {
          keyCode = "ShiftRight";
        }
        const time = useDelay
          ? delay
          : Math.floor(event.timeStamp - startTime.current);
        startTime.current = event.timeStamp;
        if (actionsRef.current.length != 0) {
          actionsRef.current.push({
            id: uuidv4(),
            type: 2,
            action: "",
            delay: time,
          });
        }
        actionsRef.current.push({
          id: uuidv4(),
          type: 1,
          webCode: keyCode,
          action: event.type,
        });
        onChange([...actionsRef.current]);
      }
      if (event instanceof MouseEvent) {
        if (
          event.target instanceof HTMLButtonElement ||
          event.target instanceof SVGElement
        )
          return;
        const time = useDelay
          ? delay
          : Math.floor(event.timeStamp - startTime.current);
        startTime.current = event.timeStamp;
        if (actionsRef.current.length != 0) {
          actionsRef.current.push({
            id: uuidv4(),
            type: 2,
            action: "",
            delay: time,
          });
        }
        actionsRef.current.push({
          id: uuidv4(),
          type: 3,
          webCode: event.button + "",
          action: event.type,
        });
        onChange([...actionsRef.current]);
      }
    };
    window.oncontextmenu = (e) => {
      e.preventDefault();
    };
    if (startRecord) {
      window.document.addEventListener("keydown", addAction);
      window.document.addEventListener("keyup", addAction);
      window.document.addEventListener("mousedown", addAction);
      window.document.addEventListener("mouseup", addAction);
    } else {
      window.document.removeEventListener("keydown", addAction);
      window.document.removeEventListener("keyup", addAction);
      window.document.removeEventListener("mousedown", addAction);
      window.document.removeEventListener("mouseup", addAction);
    }

    return () => {
      window.document.removeEventListener("keydown", addAction);
      window.document.removeEventListener("keyup", addAction);
      window.document.removeEventListener("mousedown", addAction);
      window.document.removeEventListener("mouseup", addAction);
    };
  }, [startRecord]);

  const changeAction = (newAction: MacroAction, index: number) => {
    onChange(actions.map((action, idx) => (idx == index ? newAction : action)));
  };

  const insertAction = (type: string, index: number) => {
    if (type == "time") {
      actions.splice(index, 0, {
        id: uuidv4(),
        type: 2,
        action: "time",
        delay: 0,
      });
    } else if (type == "keyboard") {
      actions.splice(index, 0, {
        id: uuidv4(),
        type: 1,
        webCode: "",
        action: "keydown",
      });
    } else if (type == "mouse") {
      actions.splice(index, 0, {
        id: uuidv4(),
        type: 3,
        webCode: "",
        action: "mousedown",
      });
    }
    onChange(_.cloneDeep(actions));
  };

  const removeAction = (index: number) => {
    actions.splice(index, 1);
    onChange(_.cloneDeep(actions));
  };

  const [hoverAction, setHoverAction] = useState(-1);

  const sensors = useSensors(
    useSensor(MouseSensor, {
      activationConstraint: {
        distance: 5,
      },
    })
  );

  const handleDragEnd = (event: any) => {
    const { active, over } = event;
    if (active.id !== over.id) {
      const activeId = actions.findIndex((action) => action.id === active.id);
      const overId = actions.findIndex((action) => action.id === over.id);
      const action = actions.splice(activeId, 1);
      actions.splice(overId, 0, ...action);
      onChange(_.cloneDeep(actions));
    }
  };

  return (
    <div className="pt-12 max-h-[80vh] overflow-y-auto pb-6">
      <Box className="flex px-8 gap-1 gap-y-12 flex-wrap items-center">
        <DndContext sensors={sensors} onDragEnd={handleDragEnd}>
          <SortableContext items={actions}>
            {actions.map((action, index) => (
              <MacroActionItem
                index={index}
                key={action.id}
                action={action}
                actions={actions}
                insertAction={insertAction}
                setHoverAction={setHoverAction}
                hoverAction={hoverAction}
                removeAction={removeAction}
                changeAction={changeAction}
                onChange={onChange}
              />
            ))}
          </SortableContext>
        </DndContext>
        <Box className="px-8">
          {startRecord ? (
            <Button
              className="macro-stop-record error-btn !px-4 flex justify-center items-center gap-1"
              onClick={(evt) => startRec(false, evt.timeStamp)}
              autoFocus={false}
            >
              <svg
                width="24"
                height="24"
                viewBox="0 0 24 24"
                fill="none"
                xmlns="http://www.w3.org/2000/svg"
              >
                <path
                  fillRule="evenodd"
                  clipRule="evenodd"
                  d="M12 22.5C17.799 22.5 22.5 17.799 22.5 12C22.5 6.20101 17.799 1.5 12 1.5C6.20101 1.5 1.5 6.20101 1.5 12C1.5 17.799 6.20101 22.5 12 22.5ZM10 8C8.89543 8 8 8.89543 8 10V14C8 15.1046 8.89543 16 10 16H14C15.1046 16 16 15.1046 16 14V10C16 8.89543 15.1046 8 14 8H10Z"
                  fill="white"
                />
              </svg>

              {t("stopRecording")}
            </Button>
          ) : (
            <Button
              className="macro-start-record primary-btn !px-4 flex justify-center items-center gap-1"
              onClick={(evt) => startRec(true, evt.timeStamp)}
            >
              <svg
                width="24"
                height="24"
                viewBox="0 0 24 24"
                fill="none"
                xmlns="http://www.w3.org/2000/svg"
              >
                <path
                  fillRule="evenodd"
                  clipRule="evenodd"
                  d="M12 22.5C17.799 22.5 22.5 17.799 22.5 12C22.5 6.20101 17.799 1.5 12 1.5C6.20101 1.5 1.5 6.20101 1.5 12C1.5 17.799 6.20101 22.5 12 22.5ZM10.4303 16.0187C10.2089 16.0175 9.98986 15.9615 9.79582 15.8556H9.79463C9.29105 15.5699 8.98629 15.0306 9.00058 14.452V9.06628C8.9851 8.49247 9.28153 7.95557 9.77558 7.6639C10.2196 7.42223 10.7613 7.44961 11.1791 7.73414L15.3077 10.4258C15.747 10.7163 16.0089 11.2115 16.0006 11.7389C16.0065 12.2818 15.7375 12.7901 15.2851 13.0889L11.1934 15.7853C10.9672 15.9353 10.7018 16.0163 10.4303 16.0187Z"
                  fill="white"
                />
              </svg>
              {actions.length == 0
                ? t("startRecording")
                : t("continueRecording")}
            </Button>
          )}
        </Box>
      </Box>
    </div>
  );
}

export default MacroActionEditor;
